import React, { Component,createRef } from 'react'
import CryptoJS from 'crypto-js'
import axios from 'axios'
/*
  实现思路
  1、编写页面
  页面中需要有三个HTML控件
  1）上传文件的上传控件
  2) 用于显示进度的进度条控件
  3）用于显示提示信息（上传成功的提示信息和上传失败的提示信息）
  2、给上传的控件绑定onChange事件，然后编写事件处理函数
  3、进行文件上传思路是将文件进行分片，file.slice(),在前端拆分，再后端合
*/
export default class App extends Component {
  constructor(){
    super()
    this.progressRef=createRef()
    this.msgRef=createRef()
  }
  /*
    将文件读取成二进制的字节数据
  */
  readFile=file=>{
    const reader=new FileReader()
    return new Promise((resolve,reject)=>{
      //当文件成功读取的时候调用onload事件
      reader.onload=()=>{
        //获取读取的文件的内容
        resolve(reader.result)
      }
      //当文件读取的时候调用onerror
      reader.onerror=reject
      //读取文件
      reader.readAsBinaryString(file)
    })
  } 
  /*
    上传文件的函数
  */
  upload=async(e)=>{
    //获取上传文件的信息
    const file=e.target.files[0];
    //调用readeFile来读取文件
    let result=await this.readFile(file)
    //通过CryptoJS来进行md5加密
    let hash=CryptoJS.MD5(result)
    //从file对象中通过对象解构获取name,size,type
    const {name,size,type}=file
    //可以给上传进度条设置最大值
    this.progressRef.current.max=size
    //进行大小的设置
    let chunkSize=1024*64
    //已经上传的文件的大小
    let uploaded=0
    const local=localStorage.getItem(hash)
    if(local){
      uploaded=Number(local)
    }

    const breakPoint=15000*1024
    //进行上传
    while(uploaded<size){
      /*
        file的slice的方法的说明
        将文件进行分片
        参数说明
        参数1：开始数值
        参数2：结束数值
        参数3：文件的类型
        返回值：Blob
      */
      let chunk=file.slice(uploaded,uploaded+chunkSize,type)
       //创建FormData对象
      let fd=new FormData()
      fd.append('name',name)
      fd.append('size',size)
      fd.append('type',type)
      fd.append('hash',hash)
      fd.append('offset',uploaded)
      fd.append('file',file)
      
    
      //进行文件上传
      try {
        axios.post('http://localhost:8080/api/upload',fd)
      } catch (error) {
        this.msgRef.current.innerText=`文件上传失败${error.message}`
      }
    
      //更新uploaed
      uploaded+=chunk.size
      //将上传的进度存储到本地
      localStorage.setItem(hash,uploaded)
      //设置进度条信息
      this.progressRef.current.value=uploaded
      //如果上传到15k
      // if(uploaded>breakPoint){
      //   return;
      // }
    }

    this.msgRef.current.innerText="上传成功!"
    
  }
  render() {
    return (
      <div>
         <div><input type="file" onChange={this.upload}/></div>
         <div>
            <progress value={0} ref={this.progressRef}></progress>
         </div>
         <div>
           <span ref={this.msgRef}></span>
         </div>
      </div>
    )
  }
}
